package markdown;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.impl.client.CloseableHttpClient;

import java.io.*;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 将原md文件中所有本地图片，上传csdn，并替换url，最终输出为新文件
 * https://blog.csdn.net/weixin_44174211/article/details/124373334
 */
public class BatchImgUploadCSDNAndReplaceUtil {

    private final static String PROTOCOL = "file:" + File.separator;

    // 源.md文件
    private final static String ORIGIN_FILE_PATH = "F:\\学习项目\\资料整理\\整理中\\notepad使用\\notepad使用.md";
    // 新文件
    private final static String TARGET_FILE_PATH = "F:\\学习项目\\资料整理\\整理中\\notepad使用\\notepad使用-1.md";

    // csdn图片服务器地址
    // 在csdn编辑界面，打开F12，上传一张图片，拿到的相关url和cookie
    // https://imgservice.csdn.net/direct/v1.0/image/upload?type=blog&rtype=markdown&x-image-template=standard&x-image-app=direct_blog&x-image-dir=direct&x-image-suffix=jpeg
    private static String IMG_SERVICE_URL = "https://imgservice.csdn.net/direct/v1.0/image/upload?watermark=&type=blog&rtype=markdown";
    private static String IMG_OSS_URL = "https://csdn-img-blog.oss-cn-beijing.aliyuncs.com/";
    // cookie
    private static String COOKIE = "uuid_tt_dd=10_19475366210-1538121857079-725505; cache_cart_num=0; Hm_ct_6bcd52f51e9b3dce32bec4a3997715ac=5744*1*weixin_44174211!1788*1*PC_VC!6525*1*10_19475366210-1538121857079-725505; UN=weixin_44174211; _ga=GA1.2.170227031.1641618177; _ga_VHSCGE70LW=GS1.1.1641736672.3.1.1641736847.0; __gads=ID=971b3e3483f36bba-2264e019c5cf006a:T=1628179596:RT=1641825689:S=ALNI_MZtiih4PmXKN4FkEO9J-DQgAWIqSA; ssxmod_itna=GqRxRiG=i=diwxBpqeTmICU24Dw8x7KmYb3D/AF+DnqD=GFDK40EYB6URtqXxGktgonProt=YuE31e8AondrDCPGnDB9AYq+DYY8Dt4DTD34DYDixibHxi5GRD0K8DbxYPuDf4DbDYRQ7DY5DhxDCUWPDwx0CIp0TIcHax/F+6PbsWihOD7y+Dlc4s9hOP4fA17yoGx0kj40O2ZIOjpYDUW+qv7GqrAwxCPRUWlqNeQ0D10cNlRi5fAqPs0kRN56XbcxDixQ9WYD; ssxmod_itna2=GqRxRiG=i=diwxBpqeTmICU24Dw8x7KmYeG9Qs4xBdWq7pi+HcaGFI=z2UEnxUOyGzSAnOy+kqz6mRNpXIgefX1oUoaSTkWAlR0+1kTlcMWktekZIt6LtbIv=1hNyzZl156XLBuwx2urhY9kMWBzL1eHsp0sXmyOz2ACTFnagrgw89qm/O4Dwc23DjKD+chDD===; UserName=weixin_44174211; UserInfo=a56f5c6b9c0e46dd9732280a76f7af70; UserToken=a56f5c6b9c0e46dd9732280a76f7af70; UserNick=%E9%93%B6%E8%BE%B0%E6%98%9F%E8%BE%89; AU=A35; BT=1644851032089; p_uid=U010000; Hm_up_6bcd52f51e9b3dce32bec4a3997715ac=%7B%22islogin%22%3A%7B%22value%22%3A%221%22%2C%22scope%22%3A1%7D%2C%22isonline%22%3A%7B%22value%22%3A%221%22%2C%22scope%22%3A1%7D%2C%22isvip%22%3A%7B%22value%22%3A%220%22%2C%22scope%22%3A1%7D%2C%22uid_%22%3A%7B%22value%22%3A%22weixin_44174211%22%2C%22scope%22%3A1%7D%7D; dc_session_id=10_1654962961749.977104; dc_sid=af966417bb01324100e76aaaa660f0d6; c_first_ref=www.baidu.com; c_first_page=https%3A//www.csdn.net/; c_dsid=11_1655734724652.601030; c_segment=1; Hm_lvt_6bcd52f51e9b3dce32bec4a3997715ac=1653569066,1654955944,1655734726; BS_coupon=20220620; __gpi=UID=0000048477c4d9e4:T=1649160157:RT=1655734731:S=ALNI_MYUslA1WnN0xHudsqufueqpf5WhZQ; c_page_id=default; c_pref=https%3A//mp.csdn.net/mp_blog/manage/article%3Fspm%3D1001.2101.3001.5448; c_ref=https%3A//mp.csdn.net/; dc_tos=rds6vy; log_Id_pv=3046; Hm_lpvt_6bcd52f51e9b3dce32bec4a3997715ac=1655737055; log_Id_view=11264; log_Id_click=1948";

    private static HttpClientUtil httpClientUtil = null;

    public static void main(String[] args) throws Exception {
        // http请求工具类
        httpClientUtil = new HttpClientUtil();
        // 读取一个文件，获取到内容
        String newContent = readFile(ORIGIN_FILE_PATH);
        // 写入到目标文件
        writeFile(newContent, TARGET_FILE_PATH);

        CloseableHttpClient httpClient = httpClientUtil.getHttpClient();
        if (httpClient != null) {
            httpClient.close();
        }
        System.out.println("处理完成！");
    }

    /**
     * 通过文件名读取一个markdown文件
     */
    private static String readFile(String originFile) throws Exception {
        FileInputStream fis = new FileInputStream(originFile);
        final InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
        BufferedReader bufferedReader = new BufferedReader(isr);
        String content = "";
        String line = null;
        while ((line = bufferedReader.readLine()) != null) {
            // 按行读取
            if (!line.isEmpty()) {
                // 处理图片
                line = handleImg(line);
            }
            content += line + "\r\n";
        }
        bufferedReader.close();
        return content;
    }

    /**
     * 判断该行是否有图片，有则上传并替换
     */
    private static String handleImg(String line) throws Exception {
        System.out.println(line);
        System.out.println("--------line--------");
        // 处理图片类型1： ![]()
        // copy至大佬的代码，原来不用正则也可以处理啊
        for (int i = 0; i < line.length(); i++) {
            if (i < line.length() - 4 && line.charAt(i) == '!' && line.charAt(i + 1) == '[') {
                int index1 = line.indexOf(']', i + 1);
                if (index1 != -1 && line.charAt(index1 + 1) == '(' && line.indexOf(')', index1 + 2) != -1) {
                    int index2 = line.indexOf(')', index1 + 2);
                    // [图片描述]
                    String picName = line.substring(i + 2, index1);
                    // (图片路径)
                    String picPath = line.substring(index1 + 2, index2).trim();
                    line = toUploadImg(line, picPath);
                }
            }
        }

        // 处理图片类型2： <img src="../../../图片/我是图片.png" style="zoom:25%;" />
        line = handleImgTag(line);

        return line;
    }

    /**
     * 处理html类型的img标签
     * 使用正则提取
     */
    private static String handleImgTag(String line) throws Exception {
        Matcher mImage = Pattern.compile("<img.*?src\\s*=\\s*(.*?)[^>]*?>", Pattern.CASE_INSENSITIVE).matcher(line);
        while (mImage.find()) {
            // 得到<img />数据
            String imgTagStr = mImage.group();
            // 匹配<img>中的src数据
            Matcher m = Pattern.compile("\\s{1}src=[\'\"]([^\'\"]+)[\'\"]").matcher(imgTagStr);
            while (m.find()) {
                String picPath = m.group(1);
                System.out.println("提取img标签图片：" + picPath);
                line = toUploadImg(line, picPath);
            }
        }
        return line;
    }

    /**
     * 上传图片之前拿到本地图片文件
     * 1.以http开头的不用上传
     * 2.将相对路径转为绝对路径
     * 3.拿不到图片文件的不用上传
     */
    private static String toUploadImg(String line, String picPath) throws Exception {
        // 保存原始地址，替换时使用
        String originPicPath = picPath;
        if (!picPath.isEmpty() && !picPath.startsWith("http")) {
            // 判断是相对路径，还是绝对路径
            // https://www.jb51.net/article/64518.htm
            if (picPath.startsWith("/") || picPath.indexOf(":") == 1) {
                // 绝对路径
            } else {
                // 相对路径转绝对路径
                // 使用该方法需要有协议头，比如http
                String absUrl = getAbsUrl(PROTOCOL + ORIGIN_FILE_PATH, picPath);
                // 切掉协议头
                picPath = absUrl.substring(PROTOCOL.length());
            }

            System.out.println("图片绝对路径：" + picPath);
            File file = new File(picPath);
            if (file == null || !file.exists() || file.isDirectory()) {
                // 可能url被编码过
                picPath = java.net.URLDecoder.decode(picPath, "UTF-8");
                file = new File(picPath);
                if (file == null || !file.exists() || file.isDirectory()) {
                    return line;
                }
            }
            System.out.println("图片需要上传：" + picPath);

            // 上传图片
            line = uploadImg(line, originPicPath, file);
        }
        return line;
    }

    /**
     * 上传图片到csdn，并替换图片路径
     */
    private static String uploadImg(String line, String originPicPath, File file) {
        // 获取oss凭据
        // 请求头
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("cookie", COOKIE);
        headerMap.put("origin", "https://editor.csdn.net");
        headerMap.put("referer", "https://editor.csdn.net/");
        headerMap.put("x-image-app", "direct_blog");
        headerMap.put("x-image-dir", "direct");
        headerMap.put("x-image-suffix", "jpeg");

        String result = httpClientUtil.sendHttpGet(IMG_SERVICE_URL, null, headerMap);
        // {"code":200,"msg":"success","message":null,
        // "data":{
        // "accessId":"LTAI5......",
        // "policy":"eyJle......",
        // "signature":"Zdxo......",
        // "dir":null,
        // "expire":"1650621246217", // 过期时间，时间戳，ms
        // "host":"https://csdn-img-blog.oss-cn-beijing.aliyuncs.com",
        // "callbackUrl":"eyJjYWxsYmFja0JvZHl......", // base64编码的数据
        // "filePath":"7.....12.png"}
        // }
        // {"code":401,"msg":"授权失败","message":null,"data":null}
        // 返回401，一般就是COOKIE失效了，重新获取下
        System.out.println(result);
        JSONObject jsonObject = JSON.parseObject(result);
        if (jsonObject != null && jsonObject.get("code") != null && "200".equals(jsonObject.get("code").toString())) {
            Object dataObject = jsonObject.get("data");
            if (dataObject != null) {
                JSONObject data = (JSONObject) JSONObject.toJSON(dataObject);
                Map<String, String> paramMap = new HashMap<>();
                paramMap.put("key", data.get("filePath").toString());
                paramMap.put("policy", data.get("policy").toString());
                paramMap.put("OSSAccessKeyId", data.get("accessId").toString());
                paramMap.put("success_action_status", "200");
                paramMap.put("signature", data.get("signature").toString());
                paramMap.put("callback", data.get("callbackUrl").toString());

                // 上传oss
                String result2 = httpClientUtil.sendHttpPostAndFile(IMG_OSS_URL, paramMap, headerMap, Arrays.asList(file));
                // {"code":200,"data":{"imageUrl":"https://img-blog.csdnimg.cn/7......589.png"},"msg":"success"}
                System.out.println(result2);
                if (result2 != null) {
                    JSONObject jsonObject2 = JSON.parseObject(result2);
                    if (jsonObject2 != null && jsonObject2.get("code") != null && "200".equals(jsonObject2.get("code").toString())) {
                        Object dataObject2 = jsonObject2.get("data");
                        if (dataObject != null) {
                            JSONObject data2 = (JSONObject) JSONObject.toJSON(dataObject2);
                            line = line.replace(originPicPath, data2.get("imageUrl").toString());
                        }
                    }
                }
            }
        }
        return line;
    }


    /**
     * 相对路径转为绝对路径
     *
     * @param absolutePath 绝对路径
     * @param relativePath 相对路径
     * @return 绝对路径
     */
    private static String getAbsUrl(String absolutePath, String relativePath) throws Exception {
        URL absoluteUrl = new URL(absolutePath);
        URL parseUrl = new URL(absoluteUrl, relativePath);
        return parseUrl.toString();
    }

    /**
     * 将内容写到目标文件
     */
    private static void writeFile(String newContent, String targetFile) throws Exception {
        File file = new File(targetFile);
        FileOutputStream fos = new FileOutputStream(file);
        OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
        osw.write(newContent);
        osw.flush();
        osw.close();
    }

}
